package net.rvb1.gwt.grad.ui.client.menu.events;

import net.rvb1.gwt.grad.ui.client.events.CancelableGwtEvent;
import net.rvb1.gwt.grad.ui.client.menu.ContextMenu;
import net.rvb1.gwt.grad.ui.client.menu.HasContextMenuHandlers;

import com.google.gwt.cell.client.Cell.Context;
import com.google.gwt.event.shared.EventHandler;

/**
 * This cancelable event is launched just before a {@link ContextMenu} is shown.<BR/>
 */
public class BeforeShowContextMenuEvent extends
    CancelableGwtEvent<BeforeShowContextMenuEvent.Handler> {

  /**
   * {@link EventHandler} used to handle {@link BeforeShowContextMenuEvent}s.
   */
  public interface Handler extends EventHandler {
    /**
     * Called when a {@link BeforeShowContextMenuEvent} event is fired.
     * 
     * @param event the {@link BeforeShowContextMenuEvent} that was fired
     */
    void onBeforeShowContextMenu(BeforeShowContextMenuEvent event);
  }

  /**
   * Handler type.
   */
  private static Type<BeforeShowContextMenuEvent.Handler> TYPE;

  /**
   * Fires a "before context menu show" event on all registered handlers in the handler manager. If
   * no such handlers exist, this method will do nothing.
   * 
   * @param <T> the item type
   * @param source the source of the handlers
   * @param item the item
   * @return the event so that the caller can check if it was canceled, or null if no handlers of
   *         this event type have been registered
   */
  public static CancelableGwtEvent<BeforeShowContextMenuEvent.Handler> fire(
      HasContextMenuHandlers source, Context context) {
    // If no handlers exist, then type can be null.
    if (TYPE != null) {
      BeforeShowContextMenuEvent event = new BeforeShowContextMenuEvent(context);
      source.fireEvent(event);
      return event;
    }
    return null;
  }

  /**
   * Gets the type associated with this event.
   * 
   * @return returns the handler type
   */
  public static Type<BeforeShowContextMenuEvent.Handler> getType() {
    if (TYPE == null) {
      TYPE = new Type<BeforeShowContextMenuEvent.Handler>();
    }
    return TYPE;
  }

  private Context context;

  /**
   * Creates a new before selection event.
   */
  protected BeforeShowContextMenuEvent(Context context) {
    this.context = context;
  }

  // The instance knows its BeforeSelectionHandler is of type I, but the
  // TYPE field itself does not, so we have to do an unsafe cast here.
  @SuppressWarnings({"unchecked", "rawtypes"})
  @Override
  public final Type<BeforeShowContextMenuEvent.Handler> getAssociatedType() {
    return (Type) TYPE;
  }

  public Context getContext() {
    return context;
  }

  @Override
  protected void dispatch(BeforeShowContextMenuEvent.Handler handler) {
    handler.onBeforeShowContextMenu(this);
  }
}